import {
  BatchAddMattertagCommand,
  BatchRemoveMattertagCommand,
  EditBillboardCommand,
  EditColorCommand,
  EditIconCommand,
  GetMattertagDataCommand,
  MattertagCloseCommand,
  MattertagNavigateCommand,
  MattertagOpenCommand,
  RegisterIconCommand,
  ResetIconCommand
} from "../command/mattertag.command"
import SdkCommand from "../command/sdk.command"
import tagChunkTypeEnum from "../enum/tagChunkType.enum"
import tagEventEnum from "../enum/tagEvent.enum"
import tagLinkTypeEnum from "../enum/tagLinkType.enum"
import tagMediaTypeEnum from "../enum/tagMediaType.enum"
import tagPropEnum from "../enum/tagProp.enum"
import transitionEnum from "../enum/transition.enum"
import SvgLoader from "../loader/svg.loader"
import Logger from "../utils/Logger"
import requestUtil from "../utils/request.util"
import { SdkCollection } from "./observable"
import { BaseException, ClassFactory, deepDiffers, exportByKey, isNum, isPositon } from "./utils"
import postMessageEnum from "../enum/postmessage.enum"
import injectEnum from "../enum/inject.enum"
function isString(e) {
  return !!e && "string" == typeof e
}
function toNum(e) {
  return e - 0
}
const re = new Set()
re.add(0)
class CustomFrame {
  iframe: any
  constructor(e) {
    this.iframe = e
  }
  mount(e) {
    e.appendChild(this.iframe)
  }
  unmount() {
    this.iframe.parentNode && this.iframe.parentNode.removeChild(this.iframe)
  }
}
class PreventActionExecutor {
  validateInput(e, t) {
    const o = e.sid
    if (!isString(o)) throw new TagIdInputException(o)
    if (!t.mattertags.getTag(o)) throw Error(e.sid + " is not a valid tag sid")
    const n = { opening: !1, navigating: !1 }
    if ("object" == typeof e.prevent && e.prevent) {
      const t = e.prevent
      n.opening = !!t.opening
      n.navigating = !!t.navigating
    }
    return { sid: o, prevent: n }
  }
  exec(e, t, o) {
    e.prevent.opening = !e.prevent.opening
    e.prevent.navigating = !e.prevent.navigating
    o.setTagCapabilities(e.sid, e.prevent)
    t.return()
  }
}
class InjectionExecutor {
  getIframeSrc: any
  constructor(e) {
    this.getIframeSrc = e
  }
  validateInput(e, t) {
    const o = e.tagId
    if (!isString(o)) throw new TagIdInputException(o)
    if (!t.getTag(o)) throw Error(e.tagId + " is not a valid tagId")
    if (!e.html || "string" != typeof e.html) throw Error(e.html + " is not valid html")
    if (!isNum(e.clientId)) throw Error("Unexpected error: unable to create iframe")
    const n = e.options || {}
    let r = "string" == typeof n.windowPath ? n.windowPath : ""
    if (r && r.split(".").filter(e => "parent" !== e && "opener" !== e).length > 0) throw Error(r + " is an unsupported window path")
    r.length > 0 && "." !== r[0] && (r = "." + r)
    try {
      if (!Function("return window" + r)().postMessage) throw Error("invalid window")
    } catch (e) {
      throw Error("problem finding a valid window with path: " + r)
    }
    const a = { on: "on", off: "off", send: "send" }
    n.messageFcnMapping &&
      (isString(n.messageFcnMapping.on) && (a.on = n.messageFcnMapping.on),
      isString(n.messageFcnMapping.off) && (a.off = n.messageFcnMapping.off),
      isString(n.messageFcnMapping.send) && (a.send = n.messageFcnMapping.send))
    const s = { w: 0, h: 0 }
    if (n.size) {
      const e = toNum(n.size.w + ""),
        t = toNum(n.size.h + "")
      isNaN(e) || isNaN(t) || ((s.w = e), (s.h = t))
    }
    return {
      tagId: o,
      clientId: e.clientId,
      html: e.html,
      options: { size: s, windowPath: r, messageFcnMapping: a }
    }
  }
  exec(e, t, o) {
    const n = (() => {
      let e
      do {
        e = Math.floor(1000000 * Math.random())
      } while (re.has(e))
      re.add(e)
      return e
    })()
    const r = (e => {
      const t = document.createElement("iframe")
      return (t.src = e), t.sandbox.add("allow-scripts"), t
    })(this.getIframeSrc())
    r.addEventListener("load", () => {
      const o = r.contentWindow
      t.return({ messengerType: postMessageEnum.POSTMESSAGE, iframeId: n }),
        o.postMessage(
          {
            type: injectEnum.SETUP,
            id: n,
            targetId: e.clientId,
            customHTML: e.html,
            windowPath: e.options.windowPath,
            messageFcnMapping: e.options.messageFcnMapping
          },
          "*"
        )
    })
    o.getTag(e.tagId).widgetFrame = {
      size: { width: e.options.size.w, height: e.options.size.h },
      frame: new CustomFrame(r)
    }
    o.commit()
  }
}
class MattertagSubFactory {
  create(e, t) {
    return t.onChanged(() => e.onChanged())
  }
}
class MattertagDataCollection {
  _data: {}
  mediaConverter: any
  constructor(e) {
    this._data = {}
    this.mediaConverter = e.mediaConverter
  }
  get data() {
    return this._data
  }
  isItemEqual(e, t) {
    return !deepDiffers(this.data[t], e.data[t])
  }
  update(e, t, o) {
    for (const s of e.getTagList()) {
      const i = e.getTag(s),
        d = t.getFloor(i.floorId),
        c = this.data[i.sid] || {}
      c.sid = i.sid
      c.enabled = i.enabled
      c.anchorPosition = exportByKey(i, "anchorPosition", c.anchorPosition)
      c.stemVector = exportByKey(i, "stemVector", c.stemVector)
      c.stemVisible = i.stemVisible
      c.label = i.label
      c.description = i.description
      c.media = this.getMedia(i, c.media)
      c.color = ((n = i), (r = "color"), ((a = (a = c.color) || {}).r = n[r].r), (a.g = n[r].g), (a.b = n[r].b), a)
      c.floorIndex = d ? d.index : -1
      c.floorInfo = c.floorInfo || {}
      c.floorInfo.id = o.getIdFromCwfId(d.id)
      c.floorInfo.sequence = d.index
      this.data[i.sid] = c
    }
    var n, r, a
    for (const t in this.data) {
      e.getTag(t) || delete this.data[t]
    }
  }
  clear() {
    this._data = {}
  }
  getMedia(e, t) {
    const o = this.mediaConverter.toSdkMedia(e.mediaType)
    return ((t = t || {}).src = e.mediaSrc), (t.type = o || tagMediaTypeEnum.NONE), t
  }
}
class EditOpacityExecutor {
  validateInput(e, t) {
    const log = new Logger("command.editOpacity")
    const o = e.sid
    if ("string" !== typeof o) throw new TagIdInputException(o)
    if (!t.getTag(o)) throw Error(e.sid + " is not a valid Mattertag sid")
    if ("number" != typeof e.opacity || isNaN(e.opacity)) throw Error(e.opacity + " is not a valid opacity value")
    let n = e.opacity
    return (n < 0 || 1 < n) && (log.warn(n, "is outside the valid range of [0, 1]"), (n = allowNum(n, 0, 1))), { sid: o, opacity: n }
  }
  exec(e, t, o, n) {
    n.changeDiscOpacity(e.sid, e.opacity), t.return()
  }
}
class TagIdInputException extends BaseException {
  constructor(e) {
    super("Expected tagId parameter to be of type string; got " + (Array.isArray(e) ? "Array" : typeof e))
  }
}
const allowNum = function (num, min, max) {
  return Math.max(min, Math.min(num, max))
}
function checkNum(num, min, max) {
  return min <= num && num <= max
}
function $(e) {
  const log = new Logger("util")
  let t, o
  return (
    !!((t = e) && "object" == typeof t && "r" in t && "g" in t && "b" in t && isNum(t.r) && isNum(t.g) && isNum(t.b)) &&
    (checkNum(e.r, 0, 1) || log.warn("The color provided should have an r value be in the range of [0, 1]"),
    checkNum(e.g, 0, 1) || log.warn("The color provided should have an g value be in the range of [0, 1]"),
    checkNum(e.b, 0, 1) || log.warn("The color provided should have an b value be in the range of [0, 1]"),
    ((o = e).r = allowNum(o.r, 0, 1)),
    (o.g = allowNum(o.g, 0, 1)),
    (o.b = allowNum(o.b, 0, 1)),
    !0)
  )
}
function getFloorIndex(e, t, o, n) {
  const log = new Logger("mattertag-util")
  const r = n.meshSubGroupsFromPoint(e)
  let a = 1 / 0,
    s = ""
  for (const t of o.rooms())
    if (r.find(e => e.meshGroup === t.meshGroup && e.meshSubgroup === t.meshSubgroup)) {
      const o = n.meshGroups.rooms.get(t.meshGroup, t.meshSubgroup),
        r = e.y - ((null == o ? void 0 : o.boundingBox.min.y) || -1 / 0)
      r < a && ((a = r), (s = t.floorId))
    }
  try {
    return t.getFloor(s).index
  } catch (e) {
    return log.debug("Unable to deduce floor index from position; defaulting to floor 0"), 0
  }
}

function convertLink(e, t, o) {
  function linkInfo(e) {
    if (!e) return
    return { label: e.label, type: o.toSdkLinkType(e.type), url: e.url, navigationData: e.navigationData }
  }
  const r = []
  for (const o of e) r.push({ type: t.toSdkChunkType(o.type), link: linkInfo(o.link), text: o.text })
  return r
}

export default {
  DescriptionChunkType: sdk => {
    sdk.addEnumToInterface({ namespace: "Mattertag", name: "DescriptionChunkType", values: tagChunkTypeEnum })
  },
  Event: sdk => {
    sdk.addEnumToInterface({ namespace: "Mattertag", name: "Event", values: tagEventEnum })
  },
  LinkType: sdk => {
    sdk.addEnumToInterface({ namespace: "Mattertag", name: "LinkType", values: tagLinkTypeEnum })
  },
  MediaType: sdk => {
    sdk.addEnumToInterface({ namespace: "Mattertag", name: "MediaType", values: tagMediaTypeEnum })
  },
  Transition: sdk => {
    sdk.addEnumToInterface({ namespace: "Mattertag", name: "Transition", values: transitionEnum })
  },
  getData: (sdk, allFunc, dependencies) => {
    allFunc.addBinding(GetMattertagDataCommand, async () =>
      dependencies.getDependencies().then(([e, t, n]) => {
        try {
          const r = []
          e.iterate(e => {
            const { id, index } = t.getFloor(e.floorId),
              fid = n.getIdFromCwfId(id),
              mediaSrc = e.mediaSrc,
              mediaType = allFunc.mediaConverter.fromTagChunkType(e.mediaType)
            r.push({
              sid: e.sid,
              label: e.label,
              description: e.description,
              parsedDescription: convertLink(e.parsedDescription, allFunc.chunkTypeConverter, allFunc.linkTypeConverter),
              mediaSrc,
              mediaType,
              media: { type: mediaType, src: mediaSrc },
              anchorPosition: { x: e.anchorPosition.x, y: e.anchorPosition.y, z: e.anchorPosition.z },
              anchorNormal: { x: e.anchorNormal.x, y: e.anchorNormal.y, z: e.anchorNormal.z },
              color: { r: e.color.r, g: e.color.g, b: e.color.b },
              enabled: e.enabled,
              floorId: index,
              floorIndex: index,
              floorInfo: { id: fid, sequence: index },
              stemVector: { x: e.stemVector.x, y: e.stemVector.y, z: e.stemVector.z },
              stemHeight: e.stemHeight,
              stemVisible: e.stemVisible
            })
          })
          return r
        } catch (e) {
          throw Error("problem getting tag data")
        }
      })
    )
    sdk.addCommandCreator({ namespace: "Mattertag", name: "getData", args: [] }, () => new GetMattertagDataCommand())
  },
  add: (sdk, THREE, exportOBJ, allFunc, dependencies) => {
    const a = {
      [tagMediaTypeEnum.NONE]: exportOBJ.TagDescriptionChunkType.none,
      [tagMediaTypeEnum.PHOTO]: exportOBJ.TagDescriptionChunkType.photo,
      [tagMediaTypeEnum.VIDEO]: exportOBJ.TagDescriptionChunkType.video,
      [tagMediaTypeEnum.RICH]: exportOBJ.TagDescriptionChunkType.rich
    }
    function getMedia(e, n, r, s) {
      if (!isPositon(e.anchorPosition)) throw Error("anchorPosition is not a valid Vector3")
      if (!isPositon(e.stemVector)) throw Error("stemVector is not a valid Vector3")
      const position = new THREE.Vector3().copy(e.anchorPosition),
        normal = new THREE.Vector3().copy(e.stemVector),
        stemHeight = normal.length()
      normal.normalize()
      let floorIndex = undefined !== e.floorIndex ? e.floorIndex : e.floorId
      undefined === floorIndex && (floorIndex = getFloorIndex(position, n, r, s))
      const floor = n.getFloorAtIndex(floorIndex)
      if (!floor) throw new Error(`Could not add Mattertag on invalid floor with index: ${floorIndex}`)
      const color = $(e.color) ? new THREE.Color(e.color.r, e.color.g, e.color.b) : exportOBJ.Color.MATTERTAG_BLUE,
        description = e.description,
        label = e.label,
        stemVisible = !e.hasOwnProperty("stemVisible") || e.stemVisible
      let media
      e.media && (media = { mediaType: a[e.media.type] || exportOBJ.TagDescriptionChunkType.none, mediaSrc: e.media.src || "" })
      new exportOBJ.AddMattertagCommand({ position, normal, floorId: floor.id }, { color, description, label, stemHeight, stemVisible, enabled: !0 })
      return media
    }
    sdk.addCommandCreator({ namespace: "Mattertag", name: "add", args: ["tags"] }, e => {
      const tags = Array.isArray(e.tags) ? e.tags : [e.tags]
      return new BatchAddMattertagCommand(tags)
    })
    allFunc.addBinding(BatchAddMattertagCommand, async e => {
      const [t, o, a] = await dependencies.getDependencies()
      const i = (function (e, t, o, n) {
        const r = [],
          a = e,
          i = a.length
        r.length = i
        for (let e = 0; e < a.length; ++e)
          try {
            r[e] = getMedia(a[e], t, o, n)
          } catch (t) {
            throw Error(`Error in tag ${e} - ${t["message"]}`)
          }
        return r
      })(e, t, o, a)
      const d = []
      d.length = i.length
      for (let t = 0; t < i.length; ++t) {
        const o = await allFunc.issueCommand(i[t])
        d[t] = o
        const r = e[t]
        r.iconId && (await allFunc.issueCommand(new EditIconCommand({ tagId: o, iconId: r.iconId })))
      }
      return d
    })
  },
  registerIcon: (sdk, THREE, allFunc) => {
    const r = {},
      a = {}
    allFunc.addBinding(RegisterIconCommand, async e => {
      const { iconId, iconSrc } = e
      if (!iconSrc || "string" != typeof iconSrc) throw Error("icon src is not a valid string")
      if (!iconId || "string" != typeof iconId) throw Error("icon id is not a valid string")
      if (a[iconId]) throw Error(iconId + " already has a registered icon")
      const i = new SvgLoader(new requestUtil.RequestQueue()),
        loadIcon = new Promise((resolve, reject) => {
          const ext = ".svg"
          if (iconSrc.indexOf(ext, iconSrc.length - ext.length) > -1)
            i.load(iconSrc).then(data => {
              const r = new THREE.Texture(data)
              r.needsUpdate = !0
              a[iconId] = r
              resolve(r.image)
            })
          else {
            const t = allFunc.loadImage(
              iconSrc,
              () => {
                a[iconId] = t
                resolve(t.image)
              },
              () => {
                reject("Failed to load " + iconSrc)
              }
            )
          }
        })
      r[iconId] = loadIcon
      try {
        await loadIcon
      } catch (e) {
        throw (delete r[iconId], Error(e as any))
      }
    })
    sdk.addCommandCreator({ namespace: "Mattertag", name: "registerIcon", args: ["iconId", "iconSrc"] }, e => new RegisterIconCommand(e))
  },
  editIcon: (sdk, THREE, allFunc, dependencies) => {
    const r = {},
      a = {}
    allFunc.addBinding(EditIconCommand, async e => {
      const [o, s] = await dependencies.getDependencies(),
        { iconId, tagId } = e
      if (!iconId || !r[iconId]) throw Error(iconId + " has not been registered as valid icon id")
      if ("string" !== typeof tagId) throw new TagIdInputException(tagId)
      if (!s.getTag(tagId)) throw Error(tagId + " is not a valid tag id")
      let c
      try {
        c = await r[iconId]
      } catch (e) {
        throw Error(e as any)
      }
      const u = a[iconId],
        p = c.naturalWidth / c.naturalHeight,
        m = new THREE.Vector3()
      p > 1 ? m.set(p, 1, 1) : m.set(1, 1 / p, 1)
      o.setOverrideMaterial(tagId, u, m)
    })
    sdk.addCommandCreator({ namespace: "Mattertag", name: "editIcon", args: ["tagId", "iconId"] }, e => new EditIconCommand(e))
  },
  resetIcon: (sdk, allFunc, dependencies) => {
    allFunc.addBinding(ResetIconCommand, async e => {
      const [t] = await dependencies.getDependencies(),
        { tagId } = e
      t.setOverrideMaterial(tagId, null, null)
    })
    sdk.addCommandCreator({ namespace: "Mattertag", name: "resetIcon", args: ["tagId"] }, e => new ResetIconCommand(e))
  },
  editBillboard: (sdk, exportOBJ, allFunc, dependencies) => {
    const MediaType = {
      [tagMediaTypeEnum.NONE]: exportOBJ.TagDescriptionChunkType.none,
      [tagMediaTypeEnum.PHOTO]: exportOBJ.TagDescriptionChunkType.photo,
      [tagMediaTypeEnum.VIDEO]: exportOBJ.TagDescriptionChunkType.video,
      [tagMediaTypeEnum.RICH]: exportOBJ.TagDescriptionChunkType.rich
    }
    dependencies.getDependencies().then(() => {
      allFunc.addBinding(EditBillboardCommand, async e => {
        const t = e.tagId
        if ("string" !== typeof t) throw new TagIdInputException(t)
        if (!e.properties) return
        const r = e.properties[tagPropEnum.LABEL],
          s = e.properties[tagPropEnum.MEDIA],
          i = e.properties[tagPropEnum.DESCRIPTION]
        if (null != r && "string" != typeof r) throw Error("Mattertag.editBillboard only accepts a string for the title field")
        if (null != i && "string" != typeof i) throw Error("Mattertag.editBillboard only accepts a string for the description field")
        if (null != s) {
          if ("string" != typeof s.src) throw Error("Mattertag.editBillboard only accepts a string for the media.src field")
          if (!Object.values(tagMediaTypeEnum).includes(s.type))
            throw Error("Mattertag.editBillboard only accepts a value from Mattertag.MediaType for the media.type field")
        }
        let d
        s && (d = { mediaType: MediaType[s.type], mediaSrc: s.src })
        const c = { label: r, description: i }
        await allFunc.issueCommand(new exportOBJ.EditMattertagCommand(e.tagId, c, d))
      })
    })
    sdk.addCommandCreator({ namespace: "Mattertag", name: "editBillboard", args: ["tag", "values"] }, e => new EditBillboardCommand(e.tag, e.values))
  },
  editColor: (sdk, THREE, exportOBJ, allFunc, dependencies) => {
    dependencies.getDependencies().then(() => {
      allFunc.addBinding(EditColorCommand, async e => {
        const r = e.color
        if (null != r && !$(r)) throw Error("Mattertag.editColor only accepts a Color object of the form {r, g, b} for the color field")
        const a = { color: new THREE.Color().setRGB(r.r, r.g, r.b) }
        await allFunc.issueCommand(new exportOBJ.EditMattertagCommand(e.tagId, a))
      })
    })
    sdk.addCommandCreator({ namespace: "Mattertag", name: "editColor", args: ["tag", "color"] }, e => new EditColorCommand(e.tag, e.color))
  },
  editOpacity: (sdk, dependencies) => {
    const command = SdkCommand.create(dependencies, new ClassFactory(EditOpacityExecutor))
    sdk.addCommandToInterface({ namespace: "Mattertag", name: "editOpacity", args: ["sid", "opacity"] }, command)
  },
  data: (sdk, allFunc, dependencies) => {
    const data = SdkCollection.create(dependencies, new MattertagSubFactory(), new ClassFactory(MattertagDataCollection, allFunc))
    sdk.addCollectionToInterface({ namespace: "Mattertag", name: "data" }, data)
  },
  injectHTML: (sdk, func, dependencies) => {
    const command = SdkCommand.create(dependencies, new ClassFactory(InjectionExecutor, func))
    sdk.addCommandToInterface({ namespace: "Mattertag", name: "injectHTML", subRoutine: "mattertag.inject", args: ["tagId", "html", "options"] }, command)
  },
  editPosition: (sdk, THREE, exportOBJ, dependencies) => {
    let r
    sdk.addCommandCreator({ namespace: "Mattertag", name: "editPosition", args: ["sid", "options"] }, e => {
      if (!r) throw Error("Edit command not bound yet")
      return r(e)
    })
    const a = new THREE.Vector3(),
      s = new THREE.Vector3()
    dependencies.getDependencies().then(function ([e, t, n, i]) {
      r = ({ sid: r, options: d }) => {
        const { stemVector: c, anchorPosition: u } = d,
          p: any = {}
        if (!isString(r)) throw new TagIdInputException(r)
        const m = e.getTag(r)
        if (!m) throw Error(`${r} was not found in the mattertag data`)
        if (u && (!isNum(u.x) || !isNum(u.y) || !isNum(u.z))) throw Error(`${u} is not a valid Vector3`)
        if (c && (!isNum(c.x) || !isNum(c.y) || !isNum(c.z))) throw Error(`${c} is not a valid Vector3`)
        let l = t.getFloor(m.floorId)
        s.copy(m.anchorPosition)
        a.copy(m.anchorNormal)
        c && (a.set(c.x, c.y, c.z), (p.stemHeight = a.length()), a.normalize())
        u && (s.set(u.x, u.y, u.z), (l = t.getFloorAtIndex(getFloorIndex(s, t, n, i))))
        const h = undefined !== d.floorIndex ? d.floorIndex : d.floorId
        if ((undefined !== h && (l = t.getFloorAtIndex(h)), !l)) throw new Error(`Could not move Mattertag to invalid floor with index: ${h}`)
        return new exportOBJ.EditMattertagCommand(r, p, undefined, { floorId: l.id, normal: a, position: s })
      }
    })
  },
  navigateToTag: (sdk, exportOBJ, allFunc) => {
    sdk.addCommandCreator({ namespace: "Mattertag", name: "navigateToTag", args: ["sid", "transitionType"] }, e => {
      const n = e.transitionType ? exportOBJ.cameraTransitionConverter.fromSdkTransition(e.transitionType) : allFunc.CameraTransitionType.Interpolate
      return new MattertagNavigateCommand(e.sid, n)
    })
    allFunc.addBinding(MattertagNavigateCommand, async e => {
      try {
        return await allFunc.issueCommand(new exportOBJ.NavigateToMattertagCommand(e.sid, e.transition)), e.sid
      } catch (t) {
        throw Error(`Could not move to tag with sid ${e.sid}`)
      }
    })
  },
  preventAction: (sdk, dependencies) => {
    const command = SdkCommand.create(dependencies, new ClassFactory(PreventActionExecutor))
    sdk.addCommandToInterface({ namespace: "Mattertag", name: "preventAction", args: ["sid", "prevent"] }, command)
  },
  remove: (sdk, exportOBJ, allFunc) => {
    sdk.addCommandCreator({ namespace: "Mattertag", name: "remove", args: ["tags"] }, function (e) {
      const o = []
      if (!e.tags) throw Error("invalid list of tags to remove")
      if (Array.isArray(e.tags)) {
        const n = e.tags,
          r = n.length
        o.length = r
        for (let e = 0; e < r; ++e) o[e] = new exportOBJ.RemoveMattertagCommand(n[e])
      } else o.push(new exportOBJ.RemoveMattertagCommand(e.tags))
      return new BatchRemoveMattertagCommand(o)
    })
    allFunc.addBinding(BatchRemoveMattertagCommand, async e => {
      const t = [],
        n = e.removeCommands
      for (const e of n) {
        const n = await allFunc.issueCommand(e)
        n && t.push(n)
      }
      return t
    })
  },
  closeBillboards: (sdk, allFunc, dependencies) => {
    sdk.addCommandCreator({ namespace: "Mattertag", name: "closeBillboards", args: ["tag"] }, e => new MattertagCloseCommand(e.tag)),
      dependencies.getDependencies().then(([e]) => {
        allFunc.addBinding(MattertagOpenCommand, async t => {
          const o = t.tag
          if (!isString(o)) throw new TagIdInputException(o)
          e.openBillboard(o)
        })
      }),
      dependencies.getDependencies().then(([e]) => {
        allFunc.addBinding(MattertagCloseCommand, async t => {
          const o = t.tag
          if (!isString(o)) throw new TagIdInputException(o)
          e.closeBillboard(t.tag)
        })
      })
  },
  onEvent: (sdk, exportOBJ, allFunc, dependencies) => {
    dependencies.getDependencies().then(([n]) => {
      const r = ["", !1],
        a = e => ((r[0] = e.id), (r[1] = e.hovering), r)
      allFunc.subscribe(exportOBJ.PinHoverChangeMessage, o => {
        o.pinType === exportOBJ.PinType.MATTERTAG && sdk.broadcast(tagEventEnum.HOVER, a, o)
      })
      const s = [""],
        i = e => ((s[0] = e.id), s)
      allFunc.subscribe(exportOBJ.PinClickedMessage, o => {
        o.pinType === exportOBJ.PinType.MATTERTAG && sdk.broadcast(tagEventEnum.CLICK, i, o)
      })
      const d = ["", ""],
        c = e => ((d[0] = n.openTag), (d[1] = e.url), d)
      allFunc.subscribe(exportOBJ.MattertagLinkOpenedMessage, t => {
        sdk.broadcast(tagEventEnum.LINK_OPEN, c, t)
      })
    })
  }
}
